#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <getopt.h>

#define MES_STR "Hello world!"

void print_usage(char *progname)
{
	printf("%s usage: \n", progname);
//	printf("-i(--ipaddr): sepcify server IP address\n");
	printf("-p(--port): sepcify server port\n");
	printf("-h(--help): print this help information\n");

	return;
}

int main(int argc, char** argv)
{
	int        sockfd = -1;
	int        on = 1;
	int        fkfd = -1;
	int        pid = -1;
	int        BACKLOG = 1024;
	int        acfd = -1;
	int        rv = -1;
	int        ch = -1;
	socklen_t  cliaddr_len;
//	int        PORT=12345;
//	char       *ID = "192.168.41.1";
	int        PORT=0;
//	char       *ID
	char       buf[1024];
	struct     sockaddr_in serv_addr;
	struct     sockaddr_in cli_addr;
	struct     option opts[] ={
//	      	   {"ipaddr", required_argument,NULL,'i'},
		   {"port", required_argument,NULL,'p'},
		   {"help", no_argument,NULL,'h'},
		   {NULL, 0, NULL, 0}
	};

	while((ch=getopt_long(argc, argv, "i:p:h", opts, NULL)) != -1 )
	{
		switch(ch)
		{
//			case'i':
//				ID=optarg;
				break;
		       	case'p':
                                PORT=atoi(optarg);
                                break;
		       	case'h':
                                print_usage(argv[0]);
                                return 0;
		}
	}
	
	if(/*!ID ||*/ !PORT)
	{
		print_usage(argv[0]);
		return 0;
	}


	sockfd=socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd<0)
	{
		printf("Create socket filetrue: %s\n",strerror(errno));
		return -1;
	}
        printf("Create socket successful: %d\n",sockfd);

	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
//	setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));



	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	rv=bind(sockfd,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(rv<0)
	{
                printf("Bind filetrue: %s\n",strerror(errno));
                return -2;
        }
        printf("socket[%d] bind on port[%d] for all IP ok\n",sockfd,PORT);

	listen(sockfd, BACKLOG);
	while(1)
	{
		printf("Start waitting for accept new client...\n");
		cliaddr_len = sizeof(cli_addr);
		acfd=accept(sockfd, (struct sockaddr*)&cli_addr,&cliaddr_len);

		pid=fork();
		if(pid<0)
		{
			printf("Fork filetrue: %s\n",strerror(errno));
			close(acfd);
		//	return -1;
		        continue;
		}
		else if(pid>0)
		{
			close(acfd);
		//	return -2;
			continue;
		}
		else
		{
//			char buf[1024];

			close(sockfd);
			printf("Start connect to client...\n");

			while(1)
			{
//				setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

				if(acfd<0)
				{
					printf("Accept new cilent filetrue: %s\n",strerror(errno));
                                        return -3;
                                }
	     
				printf("accept new client[%d:%d] on port[%d]\n",cli_addr.sin_addr.s_addr, cli_addr.sin_port, PORT);
				printf("acfd:%d\n",acfd);
			
				memset(&buf, 0, sizeof(buf));
				rv=read(acfd, buf, sizeof(buf));
				printf("rv:%d\n",rv);
				if(rv<0)
			       	{
				      	printf("Read from client [%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
				       	close(acfd);
					exit(0);
                                }
	                        if(rv==0)
                                {
					printf("connect to client[%d:%d] filetrue:%s\n",cli_addr.sin_addr.s_addr, cli_addr.sin_port, strerror(errno));
				      	//printf("Read from client [%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
				       	close(acfd);
					exit(0);
                                }
				printf("Read data from client:%d\n", rv);
				printf("Read from client:%s\n",buf);
					
				rv=write(acfd, MES_STR, strlen(MES_STR));
				printf("rv:%d\n",rv);
				if(rv<0)
		        	{
					printf("Write to client[%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
				       	close(acfd);
					exit(0);
				}
				printf("write to client data:%d\n",rv);
			
			/*	memset(&buf, 0, sizeof(buf));
				rv=read(acfd, buf, sizeof(buf));
				if(rv<0)
			       	{
				      	printf("Read from client [%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
				       	close(acfd);
					exit(0);
                                }
	                        if(rv==0)
                                {
                                         printf("Client connect to server get disconnect!\n");
			      	         close(acfd);
				       	 exit(0);
                                }
			*/	
			}
			close(acfd);
			}
	}
//		printf("Read :%s\n", buf);
		close(sockfd);
		return 0;
}

